/**
 * @description: 材质处理
 * @file: material.ts
 * @author: Evan
 * @date: 2025.07.17 14:39:37
 * @week: 周四
 * @version: V
 */

import { Scene } from '../class'
import DefaultConfig from '../data/config'
import * as MD from '../data/methods'
const { THREE, Hooks } = MD

type ST = InstanceType<typeof Scene>

const { changeTransparent } = Hooks.useMaterial()

export function material(core: ST) {
  return {
    add() {
      const gui = core.gui

      if (!core.container) return
      const group = gui.addFolder('材质')

      const guiOpts = core.guiOpts
      group.add(guiOpts, 'transformMaterial').name('转换标准材质')
      group
        .add(guiOpts, 'glisten')
        .name('材质反光')
        .onChange(() => this.glistenToggle())
      group
        .add(guiOpts, 'groundReflection')
        .name('地面反光')
        .onChange(() => this.groundGlisten())
      group
        .add(guiOpts, 'side')
        .name('双面材质')
        .onChange(() => this.sideMaterialToggle())
      group
        .add(guiOpts, 'opacitySkin')
        .name('材质透明')
        .onChange(() => this.opacitySkin())
      group
        .add(guiOpts, 'opacity', 0, 1)
        .name('透明度')
        .onChange(() => this.opacitySkin())

      group.close()
    },

    // 材质反光
    glistenToggle() {
      let roughness = core.guiOpts.glisten ? 0 : 0.9

      core.modelGroup?.traverse((el: any) => {
        if (el.isMesh) {
          if (el.material instanceof Array) {
            el.material.forEach((mat: MD.THREE.MeshPhysicalMaterial) => {
              mat.roughness = roughness
            })
          } else {
            el.material.roughness = roughness
          }
        }
      })
    },

    // 地面反光
    groundGlisten() {
      let roughness = core.guiOpts.groundReflection ? 0 : 0.9
      core.modelGroup?.traverse((el: any) => {
        if (el.isMesh && DefaultConfig.receiveShadowName.find(it => el.name.indexOf(it) > -1)) {
          if (el.material instanceof Array) {
            el.material.forEach((mat: MD.THREE.MeshPhysicalMaterial) => {
              mat.roughness = roughness
            })
          } else {
            el.material.roughness = roughness
          }
        }
      })
    },

    // 双面材质
    sideMaterialToggle() {
      const side = core.guiOpts.side ? THREE.DoubleSide : THREE.FrontSide

      if (!core.modelGroup) return
      core.modelGroup.traverse((el: any) => {
        if (el.isMesh) {
          if (el.material instanceof Array) {
            el.material.forEach((mat: MD.THREE.Material) => {
              mat.side = side
            })
          } else {
            el.material.side = side
          }
        }
      })
    },

    // 透明
    opacitySkin() {
      const { opacitySkin, opacity } = core.guiOpts

      core.modelGroup?.traverse((el: any) => {
        if (DefaultConfig.transparentName.find(it => el.name.indexOf(it) > -1)) {
          changeTransparent(el, opacitySkin ? opacity : 1)
        }
      })
    }
  }
}
